package com.ccrfid.rmc6.resource.video;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.poi.PoiCameraEntity;
import com.ccrfid.rmc6.entity.video.VideoCameraEntity;
import com.ccrfid.rmc6.entity.video.VideoCameraView;
import com.ccrfid.rmc6.pojo.dto.VideoCameraDto;
import com.ccrfid.rmc6.pojo.param.PageParam;
import com.ccrfid.rmc6.repository.search.Criterion;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.service.video.VideoCameraService;
import com.ccrfid.rmc6.service.video.VideoOrgService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Path("/video/cameras")
@Produces(MediaType.APPLICATION_JSON)
public class VideoCameraResource {
    private static final Logger logger = LoggerFactory.getLogger(VideoCameraResource.class);
    @Context
    private HttpServletRequest httpServletRequest;
    @Autowired
    private VideoCameraService videoCameraService;
    @Autowired
    private VideoOrgService videoOrgService;

    @GET
    public List<VideoCameraView> getAllVideoCameraInfo(@QueryParam("floorNumber") Integer floorNumber,
                                                       @QueryParam("pos") String pos) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (floorNumber != null) {
            criteria.add(new Criterion("floorNumber", Criterion.Operator.EQ, floorNumber));
        }
        if (pos != null) {
            if (pos.equalsIgnoreCase("Null")) {
                criteria.add(new Criterion("pos", Criterion.Operator.NULL, pos));
            } else if (pos.equalsIgnoreCase("NotNull")) {
                criteria.add(new Criterion("pos", Criterion.Operator.NOT_NULL, pos));
            }
        }
        List<VideoCameraView> list = videoCameraService.getAllVideoCameraInfo(criteria, Sort.by(new ArrayList<>()));
        return list;
    }

    @GET
    @Path("search")
    public Page<VideoCameraView> getVideoCameraInfoPage(@QueryParam("cameraSn") String cameraSn,
                                                        @QueryParam("cameraName") String cameraName,
                                                        @QueryParam("orgSn") String orgSn,
                                                        @QueryParam("floorNumber") Integer floorNumber,
                                                        @QueryParam("pos") String pos,
                                                        @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (cameraSn != null) {
            criteria.add(new Criterion("cameraSn", Criterion.Operator.EQ, cameraSn));
        }
        if (cameraName != null) {
            criteria.add(new Criterion("cameraName", Criterion.Operator.LIKE, '%' + cameraName + '%'));
        }
        if (floorNumber != null) {
            criteria.add(new Criterion("floorNumber", Criterion.Operator.EQ, floorNumber));
        }
        if (orgSn != null) {
            List<String> orgSnList = videoOrgService.getSubVideoOrgSnList(orgSn);
            orgSnList.add(orgSn);
            criteria.add(new Criterion("orgSn", Criterion.Operator.IN, orgSnList));
        }
        if (pos != null) {
            if (pos.equalsIgnoreCase("Null")) {
                criteria.add(new Criterion("pos", Criterion.Operator.NULL, pos));
            } else if (pos.equalsIgnoreCase("NotNull")) {
                criteria.add(new Criterion("pos", Criterion.Operator.NOT_NULL, pos));
            }
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        Page<VideoCameraView> page = videoCameraService.getVideoCameraInfoPage(criteria, pageRequest);
        return page;
    }

    @GET
    @Path("{id}")
    public VideoCameraEntity getVideoCamera(@PathParam("id") Long cameraId) {
        VideoCameraEntity entity = videoCameraService.getVideoCamera(cameraId);
        return entity;
    }

    @GET
    @Path("{id}/linkage-info")
    public VideoCameraDto getCameraLinkageInfo(@PathParam("id") Long cameraId) {
        return videoCameraService.getCameraLinkageInfo(cameraId, httpServletRequest.getRemoteAddr());
    }

    @GET
    @Path("{id}/{protocol}-preview-url")
    public String getPreviewUrl(@PathParam("id") Long cameraId, @PathParam("protocol") String protocol) {
        String clientIp = getRequestUrlIp(httpServletRequest.getRequestURL().toString());
        logger.debug("clientIp: {}", clientIp);
        return videoCameraService.getPreviewUrl(cameraId, protocol, clientIp);
    }

    private static String getRequestUrlIp(String requestUrl) {
        Pattern pattern = Pattern.compile("//*.*.*.*:");
        Matcher matcher = pattern.matcher(requestUrl);
        if (matcher.find()) {
            String ip = matcher.group(0);
            return ip.substring(2, ip.length() - 1);
        }
        return "";
    }

    @GET
    @Path("{id}/{protocol}-playback-url")
    public String getPlaybackUrl(@PathParam("id") Long cameraId,
                                 @PathParam("protocol") String protocol,
                                 @QueryParam("startTime") Timestamp startTime,
                                 @QueryParam("stopTime") Timestamp stopTime) {
        String clientIp = getRequestUrlIp(httpServletRequest.getRequestURL().toString());
        logger.debug("clientIp: {}", clientIp);
        return videoCameraService.getPlaybackUrl(cameraId, protocol, startTime, stopTime, clientIp);
    }

    @GET
    @Path("video-client-preview-url")
    public String getVideoClientPreviewUrl(@QueryParam("cameraId") List<Long> cameraIdList,
                                           @QueryParam("miniUI") Integer miniUI,
                                           @QueryParam("clear") Integer clear,
                                           @QueryParam("wndSelect") Integer wndSelect,
                                           @QueryParam("httpsFlag") Integer httpsFlag) {
        return videoCameraService.getVideoClientPlayUrl("PlayReal", cameraIdList, miniUI, clear, wndSelect, httpsFlag, null, null);
    }

    @GET
    @Path("video-client-playback-url")
    public String getVideoClientPlaybackUrl(@QueryParam("cameraId") List<Long> cameraIdList,
                                            @QueryParam("miniUI") Integer miniUI,
                                            @QueryParam("clear") Integer clear,
                                            @QueryParam("wndSelect") Integer wndSelect,
                                            @QueryParam("httpsFlag") Integer httpsFlag,
                                            @QueryParam("startTime") Timestamp startTime,
                                            @QueryParam("stopTime") Timestamp stopTime) {

        return videoCameraService.getVideoClientPlayUrl("PlayBack", cameraIdList, miniUI, clear, wndSelect, httpsFlag, startTime, stopTime);
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public VideoCameraEntity createVideoCamera(VideoCameraEntity entity) throws AppException {
        return videoCameraService.createVideoCamera(entity);
    }

    @PUT
    @Path("{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    public VideoCameraEntity updateVideoCamera(@PathParam("id") Long cameraId, VideoCameraEntity entity)
            throws AppException {
        return videoCameraService.updateVideoCamera(cameraId, entity);
    }

    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
    public int deleteVideoCamerasInfo(List<Long> idList) throws AppException {
        if (idList == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return videoCameraService.deleteVideoCamerasInfo(idList);
    }

    @GET
    @Path("{id}/position")
    public PoiCameraEntity getCameraPosition(@PathParam("id") Long cameraId) throws AppException {
        return videoCameraService.getCameraPosition(cameraId);
    }

    @PUT
    @Path("{id}/position")
    @Consumes(MediaType.APPLICATION_JSON)
    public PoiCameraEntity updateCameraPosition(@PathParam("id") Long cameraId, PoiCameraEntity entity)
            throws AppException {
        return videoCameraService.updateCameraPosition(cameraId, entity);
    }

    @DELETE
    @Path("{id}/position")
    public Boolean deleteCameraPosition(@PathParam("id") Long cameraId) {
        return videoCameraService.deleteCameraPosition(cameraId);
    }

}
